package pATT.decisionMaking;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Observable;
import java.util.StringTokenizer;
import java.util.Vector;

import pATT.core.SelectedTag;
import pATT.core.Tag;
import pATT.logger.Message;
import pATT.profile.Profile;
import pATT.profilingAlgorithm.PersonalSearcher.DropLittleWords;
import pATT.profilingAlgorithm.PersonalSearcher.DropNumbers;
import pATT.profilingAlgorithm.PersonalSearcher.ENGLISHStemmer;
import pATT.profilingAlgorithm.PersonalSearcher.FrequencyVectorCreator;
import pATT.profilingAlgorithm.PersonalSearcher.HTMLDocument;
import pATT.profilingAlgorithm.PersonalSearcher.Instance;
import pATT.profilingAlgorithm.PersonalSearcher.InstanceSet;
import pATT.profilingAlgorithm.PersonalSearcher.ObjectValuePair;
import pATT.profilingAlgorithm.PersonalSearcher.Recommendation;
import pATT.profilingAlgorithm.PersonalSearcher.StopWords;
import pATT.profilingAlgorithm.PersonalSearcher.Tree;






public class DMPersonalSearcher extends DMAlgorithm {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	static private 		double CONFIDENCE_THRESHOLD = 0.6;
	static private 		float FEEDBACK_HOT = 1;
	static private 		float FEEDBACK_MEDIUM = new Double(0.5).floatValue();
	static private 		float FEEDBACK_COLD = -1;
	static public 		InstanceSet validation_set = new InstanceSet();
	private Tree tree;
//	private String category = "";
	private static StopWords stops = new StopWords("ENGLISH");
	private static ENGLISHStemmer 	stemmer = new ENGLISHStemmer();
	
	/** The current category selection method */
	private int m_CategorySelection = 0;

	/* Attribute selection methods */
	public static final int CATEGORY_BANDS = 0;
	public static final int CATEGORY_BIOMEDICAL = 1;
	public static final int CATEGORY_GOATS = 2;
	public static final int CATEGORY_SHEEP = 3;
	public static final Tag [] TAGS_SELECTION = {
		new Tag(CATEGORY_BANDS, "Bands"),
		new Tag(CATEGORY_BIOMEDICAL, "BioMedical"),
		new Tag(CATEGORY_GOATS, "Goats"),
		new Tag(CATEGORY_SHEEP, "Sheep")
	};


	@Override
	public String makeDecision(Vector sit, Profile p) {

		String category = TAGS_SELECTION[m_CategorySelection].getReadable();
		System.out.println("------------>ACA111:  "+category);
		if(!new File(Message.PATH_DM_PS_CATEGORY + category).isDirectory()){
			//TODO si no es la carpeta de una categoria valida lanza null.
			return null;
		}
		tree = (Tree)p.getComponents().get(0);
		String path = sit.get(0).toString();
		loadValidation(path);

		return learnFeedback();
	}

	public void update(Observable arg0, Object arg1) {
		// TODO Auto-generated method stub

	}

	/**Este metodo recupera los documentos de lo que traeria supuestamente el motor 
	 * de busqueda, segun las palabras que ingreso el usuario
	 * @param object */
	public void loadValidation(String path){

		Instance instance;
		HTMLDocument doc;
		FrequencyVectorCreator vc;

//		String path = Message.PATH_DM_PERSONAL; TODO ahora se levanta el archivo, no se agarra por detras de la aplicacion
		Vector	v = readFromFile(path); 
//		Settings.setValidationFiles(v);
//		VocabularyDictionary vocabulary = new VocabularyDictionary();
//		ClassesDictionary classsummary = new ClassesDictionary();

		int total_size = v.size();

		System.out.println("TEST SET:"+total_size);

		int i=0;
		int garbage=0;


		while (i<total_size) {

			if (garbage==50)
				System.out.println(i+1);
			String dia = "";
			String  anio = "";
			String hora = "";
			String min = ""; 
			String seg = "";
			int mes = 0;			
			String feed = "";
			String clas = "";
			String url = "";
			String file = (String)v.elementAt(i);
			if (file.indexOf("|")>0){
				String line = file;
//				file = file.substring(0,file.indexOf("|"))+".txt";
				file = file.substring(0,file.indexOf("|"));
				line = line.substring(line.indexOf("|")+1);
				feed = line.substring(0,line.indexOf("|"));
				line = line.substring(line.indexOf("|")+1);
				url = line.substring(0,line.indexOf("|"));
				line = line.substring(line.indexOf("|")+1);
				line = line.substring(0,line.indexOf("|"));
				line = line.substring(4);

				StringTokenizer st = new StringTokenizer(line);

				String mess = st.nextToken().trim();
				mes = 0; 
				if (mess.equals("Jan"))  mes = 1;
				if (mess.equals("Feb"))  mes = 2;
				if (mess.equals("Mar"))  mes = 3;
				if (mess.equals("Apr"))  mes = 4;
				if (mess.equals("May"))  mes = 5;
				if (mess.equals("Jun"))  mes = 6;
				if (mess.equals("Jul"))  mes = 7;
				if (mess.equals("Aug"))  mes = 8;
				if (mess.equals("Sep"))  mes = 9;
				if (mess.equals("Oct"))  mes = 10;
				if (mess.equals("Nov"))  mes = 11;
				if (mess.equals("Dec"))  mes = 12;

				dia = st.nextToken().trim();
				String time = st.nextToken().trim();

				StringTokenizer st1 = new StringTokenizer(time,":");
				hora = st1.nextToken().trim();
				min = st1.nextToken().trim();
				seg = st1.nextToken().trim();			

				st.nextToken();
				anio = st.nextToken().trim();
			}
			else
				file = file.substring(0,file.indexOf("|"));

			String text = "";
			try {
				text = unLoadPage(file);
			} catch (IOException e) {
				e.printStackTrace();
			}					
			doc = new HTMLDocument(text,file);
			vc = new FrequencyVectorCreator();
			/*
			String feed=file.substring(0,file.lastIndexOf(System.getProperty("file.separator")));
			String clas=feed.substring(0,feed.lastIndexOf(System.getProperty("file.separator")));
			feed=feed.substring(feed.lastIndexOf(System.getProperty("file.separator"))+1);
			clas=clas.substring(clas.lastIndexOf(System.getProperty("file.separator"))+1);
			 */
			instance = new Instance("INSTANCE # "+i, vc.getVector(doc),file,clas.toUpperCase());
			instance.setUrl(url);
			Date date = new Date();
			date.setDate(new Integer(dia).intValue());
			date.setMonth(mes);
			date.setYear(new Integer(anio).intValue());
			date.setHours(new Integer(hora).intValue());
			date.setMinutes(new Integer(min).intValue());
			date.setSeconds(new Integer(seg).intValue());

			instance.setDate(date.getTime());

			if (feed.toUpperCase().equals("HOT"))
				instance.setFeedback(FEEDBACK_HOT);
			if (feed.toUpperCase().equals("COLD"))
				instance.setFeedback(FEEDBACK_COLD);
			if (feed.toUpperCase().equals("MEDIUM"))
				instance.setFeedback(FEEDBACK_MEDIUM);

			instance.setTxtFeedback(feed.toUpperCase());
//			if (Settings.getEnableStopWords()){
//			StopWords stops = Settings.getStopWords();
			instance = stops.applyFilter(instance);
//			}

			DropNumbers numbers = new DropNumbers();
			instance = numbers.applyFilter(instance);

//			if (Settings.getEnableStemming()){
//			Stemmer stemmer = Settings.getStemmingAlgorithm();
			instance = stemmer.applyFilter(instance);
//			}

			DropLittleWords littlewords = new DropLittleWords(2);
			instance = littlewords.applyFilter(instance);

//			classsummary.add(instance);
			instance.normalizeSquare();
			validation_set.addInstance(instance);
			i++;
		}
	}

	private static Vector readFromFile(String path){
		try{
			Vector<String> aux=new Vector<String>();
			BufferedReader bufferDirecciones;
			bufferDirecciones= new BufferedReader(new FileReader(path));
			String input = new String();
			while ((input = bufferDirecciones.readLine()) != null) {
				aux.addElement(input);
			}
			bufferDirecciones.close();
			return aux;
		}catch(IOException e) {return null;}
	}


	public String learnFeedback(){
		String decision = "";
		double score = 0;
		//---------------------calcular accurracy---------------------
		for (Enumeration enum1 = validation_set.getEnumeration(); enum1.hasMoreElements() ;) {
			String in = (String)enum1.nextElement();
			Instance i = (Instance)validation_set.getInstance(in);
			Recommendation r = new Recommendation(i);

			ObjectValuePair obj = tree.evaluateRecommendation(r);
			double conf = obj.getValue().doubleValue();
			r.setConfidence(conf);

			float real_feedback=0;
			if (i.getTxtFeedback().equals("HOT"))
				real_feedback = FEEDBACK_HOT;

			if (i.getTxtFeedback().equals("COLD"))
				real_feedback = FEEDBACK_COLD;
			if (i.getTxtFeedback().equals("MEDIUM"))
				real_feedback = FEEDBACK_MEDIUM;
			score = score + Math.abs(conf-real_feedback);

			if (conf>CONFIDENCE_THRESHOLD){
				decision += "Recommended--> "+r.getInstance().getUrl()+ "  - Confidence: "+ conf +'\n';
			}
			else{
				decision += "Not recommended--> "+r.getInstance().getUrl() +"  - Confidence: " +conf+'\n';
			}
		}
		return decision;
	}

	private String unLoadPage(String file) throws IOException{
		String path = Message.PATH_DM_PS_CATEGORY;
//		"pATT/PersonalSearcher/files/Bands/"
		StringBuffer stringbuffer = new StringBuffer();
		try{
			String category = TAGS_SELECTION[m_CategorySelection].getReadable();
			System.out.println("------------>ACA22222:  "+category);
			DataInputStream datainputstream = new DataInputStream(new BufferedInputStream(new FileInputStream(path+ category+"/" +file)));
			String s = null;
			while((s = datainputstream.readLine()) != null){
				s=s+" ";
				stringbuffer.append(s);
			}
		}catch(Exception _ex){}
		return stringbuffer.toString();
	}

	@Override
	public boolean hasInstances() {
		return true;
	}
	/**
	 * Gets the method used to select attributes for use in the
	 * linear regression. 
	 *
	 * @return the method to use.
	 */
	public SelectedTag getCategory() {

		return new SelectedTag(m_CategorySelection, TAGS_SELECTION);
	}

	/**
	 * Sets the method used to select attributes for use in the
	 * linear regression. 
	 *
	 * @param method the attribute selection method to use.
	 */
	public void setCategory(SelectedTag method) {

		if (method.getTags() == TAGS_SELECTION) {
			m_CategorySelection = method.getSelectedTag().getID();
		}
	}

	/**
	 * Returns the tip text for this property
	 * @return tip text for this property suitable for
	 * displaying in the explorer/experimenter gui
	 */
	public String categoryTipText() {
		return "Set an available category for use this algorithm ";
	}

}
